#include "imglib/winbmp.h"
#include "imglib/imageclass.h"

namespace img {

template <class R>
static void generic_init(bitmap_info<R> & info, const R & img)
{
	int w = img.width(), h = img.height();
	if (img.order() == top_down)
		h = - h;

	BITMAPINFOHEADER & header = info.bmiHeader;
	memset(&header, 0, sizeof(BITMAPINFOHEADER));
	header.biSize			= sizeof(BITMAPINFOHEADER); 
	header.biWidth			= w; 
	header.biHeight			= h;
	header.biPlanes			= 1; 
	header.biCompression	= BI_RGB; 
}

BITMAPINFO * ComposeBitmapInfo(bitmap_info<bitmap> & info, const bitmap & bmp, COLORREF foreground, COLORREF background)
{
	generic_init(info, bmp);

	info.bmiHeader.biBitCount = 1; 
	
	RGBQUAD & fg = info.bmiColors[1];

	fg.rgbBlue	= GetBValue(foreground);
	fg.rgbGreen	= GetGValue(foreground);
	fg.rgbRed	= GetRValue(foreground);

	RGBQUAD & bg = info.bmiColors[0];

	bg.rgbBlue	= GetBValue(background);
	bg.rgbGreen	= GetGValue(background);
	bg.rgbRed	= GetRValue(background);

	return reinterpret_cast<BITMAPINFO *>(&info.bmiHeader);
}

BITMAPINFO * ComposeBitmapInfo(bitmap_info<mono_byte_image> & info, const mono_byte_image & img)
{
	generic_init(info, img);

	info.bmiHeader.biBitCount = 8;

	for (int i = 0; i < 256; ++i) {
		RGBQUAD & q = info.bmiColors[i];
		q.rgbBlue = q.rgbGreen = q.rgbRed = i;
		q.rgbReserved = 0;
	}

	return reinterpret_cast<BITMAPINFO *>(&info.bmiHeader);
}

BITMAPINFO * ComposeBitmapInfo(bitmap_info<small_byte_image> & info, const small_byte_image & img)
{
	generic_init(info, img);

	info.bmiHeader.biBitCount = 24; 

	return reinterpret_cast<BITMAPINFO *>(&info.bmiHeader);
}

BITMAPINFO * ComposeBitmapInfo(bitmap_info<byte_image> & info, const byte_image & img)
{
	generic_init(info, img);

	info.bmiHeader.biBitCount = 32; 

	return reinterpret_cast<BITMAPINFO *>(&info.bmiHeader);
}

void DrawBitmap(HDC hDC, int xd, int yd, int wd, int hd, int xs, int ys, const bitmap & bmp, COLORREF foreground, COLORREF background) 
{
	bitmap_info<bitmap> info;
	ys = bmp.height() - hd - ys;
	SetDIBitsToDevice(hDC, xd, yd, wd, hd, xs, ys, 0, bmp.height(), bmp.data(), 
		ComposeBitmapInfo(info, bmp, foreground, background), 
		DIB_RGB_COLORS);
}


void StretchBitmap(HDC hDC, int xd,	int yd, int wd, int hd, int xs, int ys, int ws,	int hs,	const bitmap & bmp, COLORREF foreground, COLORREF background, long ROP) 
{
	bitmap_info<bitmap> info;
	ys = bmp.height() - hs - ys;
	StretchDIBits(hDC, xd, yd, wd, hd, xs, ys, ws, hs, bmp.data(), 
		ComposeBitmapInfo(info, bmp, foreground, background), 
		DIB_RGB_COLORS, ROP);
}

/*
void BlendBitmap(HDC hDC, int xd, int yd, int wd, int hd, int xs, int ys,	int ws,	int hs,	const bitmap & bmp, COLORREF foreground, COLORREF background, unsigned char alpha)
{
	bitmap_info<bitmap> info;
	memset(&info, 0, sizeof(bitmap_info));

	BITMAPINFOHEADER & header = info.bmiHeader;
										  
	int w = bmp.width(), h = bmp.height();

	if (bmp.order() != bottom_up) {
		h = - h;
	}

	header.biSize			= sizeof(BITMAPINFOHEADER); 
	header.biWidth			= w; 
	header.biHeight			= h; 
	header.biPlanes			= 1; 
	header.biBitCount		= 1; 
	header.biCompression	= BI_RGB;
	
	RGBQUAD & fg = info.bmiColors[1];

	fg.rgbBlue	= GetBValue(foreground);
	fg.rgbGreen	= GetGValue(foreground);
	fg.rgbRed	= GetRValue(foreground);

	RGBQUAD & bg = info.bmiColors[0];

	bg.rgbBlue	= GetBValue(background);
	bg.rgbGreen	= GetGValue(background);
	bg.rgbRed	= GetRValue(background);

	BITMAPINFO * pinfo = reinterpret_cast<BITMAPINFO *>(&info);

	BLENDFUNCTION blend;
	blend.BlendOp = AC_SRC_OVER;
	blend.BlendFlags = 0;
	blend.SourceConstantAlpha = alpha;
	blend.AlphaFormat = 0;

	AlphaDIBBlend(hDC, xd, yd, wd, hd, bmp.data(), pinfo, DIB_RGB_COLORS, 
		xs, ys, ws, hs, blend);
}
*/

} // img
